{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "nasty-intention",
   "metadata": {
    "id": "nasty-intention"
   },
   "source": [
    "# Colab Demo"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "previous-bacon",
   "metadata": {
    "id": "previous-bacon"
   },
   "source": [
    "## Dependencies and Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "complicated-receiver",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-06-18T06:34:38.757647Z",
     "start_time": "2021-06-18T06:34:37.545968Z"
    },
    "cellView": "form",
    "id": "complicated-receiver"
   },
   "outputs": [],
   "source": [
    "#@title Install dependencies\n",
    "\n",
    "!pip install -q torchaudio omegaconf\n",
    "\n",
    "import torch\n",
    "from pprint import pprint\n",
    "from omegaconf import OmegaConf\n",
    "from IPython.display import Audio, display\n",
    "\n",
    "torch.hub.download_url_to_file('https://raw.githubusercontent.com/snakers4/silero-models/master/models.yml',\n",
    "                               'latest_silero_models.yml',\n",
    "                               progress=False)\n",
    "models = OmegaConf.load('latest_silero_models.yml')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7oQde2ZNE-ok",
   "metadata": {
    "id": "7oQde2ZNE-ok"
   },
   "source": [
    "## List models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "pacific-injury",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-06-18T06:34:47.677954Z",
     "start_time": "2021-06-18T06:34:47.665753Z"
    },
    "id": "pacific-injury"
   },
   "outputs": [],
   "source": [
    "# see latest avaiable models\n",
    "available_languages = list(models.tts_models.keys())\n",
    "print(f'Available languages {available_languages}')\n",
    "\n",
    "for lang in available_languages:\n",
    "    _models = list(models.tts_models.get(lang).keys())\n",
    "    print(f'Available models for {lang}: {_models}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aebc6429",
   "metadata": {},
   "source": [
    "## V4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "14f49758",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "\n",
    "language = 'ru'\n",
    "model_id = 'v4_ru'\n",
    "device = torch.device('cpu')\n",
    "\n",
    "model, example_text = torch.hub.load(repo_or_dir='snakers4/silero-models',\n",
    "                                     model='silero_tts',\n",
    "                                     language=language,\n",
    "                                     speaker=model_id)\n",
    "model.to(device)  # gpu or cpu"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "98a29010",
   "metadata": {},
   "source": [
    "### Speakers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9ae5f9dc",
   "metadata": {},
   "outputs": [],
   "source": [
    "model.speakers"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6beca794",
   "metadata": {},
   "source": [
    "### Text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3bab211a",
   "metadata": {},
   "outputs": [],
   "source": [
    "sample_rate = 48000\n",
    "speaker = 'xenia'\n",
    "put_accent=True\n",
    "put_yo=True\n",
    "example_text = 'В недрах тундры выдры в г+етрах т+ырят в вёдра ядра к+едров.'\n",
    "\n",
    "audio = model.apply_tts(text=example_text,\n",
    "                        speaker=speaker,\n",
    "                        sample_rate=sample_rate,\n",
    "                        put_accent=put_accent,\n",
    "                        put_yo=put_yo)\n",
    "print(example_text)\n",
    "display(Audio(audio, rate=sample_rate))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "25a1ab3a",
   "metadata": {},
   "source": [
    "### SSML"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0c29189f",
   "metadata": {},
   "outputs": [],
   "source": [
    "ssml_sample = \"\"\"\n",
    "              <speak>\n",
    "              <p>\n",
    "                  Когда я просыпаюсь, <prosody rate=\"x-slow\">я говорю довольно медленно</prosody>.\n",
    "                  Пот+ом я начинаю говорить своим обычным голосом,\n",
    "                  <prosody pitch=\"x-high\"> а могу говорить тоном выше </prosody>,\n",
    "                  или <prosody pitch=\"x-low\">наоборот, ниже</prosody>.\n",
    "                  Пот+ом, если повезет – <prosody rate=\"fast\">я могу говорить и довольно быстро.</prosody>\n",
    "                  А еще я умею делать паузы любой длины, например, две секунды <break time=\"2000ms\"/>.\n",
    "                  <p>\n",
    "                    Также я умею делать паузы между параграфами.\n",
    "                  </p>\n",
    "                  <p>\n",
    "                    <s>И также я умею делать паузы между предложениями</s>\n",
    "                    <s>Вот например как сейчас</s>\n",
    "                  </p>\n",
    "              </p>\n",
    "              </speak>\n",
    "              \"\"\"\n",
    "\n",
    "sample_rate = 48000\n",
    "speaker = 'xenia'              \n",
    "audio = model.apply_tts(ssml_text=ssml_sample,\n",
    "                        speaker=speaker,\n",
    "                        sample_rate=sample_rate)\n",
    "display(Audio(audio, rate=sample_rate))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66fc3785",
   "metadata": {},
   "source": [
    "### Random speaker"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d304ba2d",
   "metadata": {},
   "source": [
    "#### Generate new"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "93115390",
   "metadata": {},
   "outputs": [],
   "source": [
    "sample_rate = 48000\n",
    "speaker = 'random'\n",
    "\n",
    "example_text = 'В недрах тундры выдры в г+етрах т+ырят в вёдра ядра к+едров.'\n",
    "\n",
    "audio = model.apply_tts(text=example_text,\n",
    "                        speaker=speaker,\n",
    "                        sample_rate=sample_rate)\n",
    "print(example_text)\n",
    "display(Audio(audio, rate=sample_rate))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30ecc807",
   "metadata": {},
   "source": [
    "#### Save generated speaker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "013ca793",
   "metadata": {},
   "outputs": [],
   "source": [
    "voice_path = 'test_voice.pt'\n",
    "model.save_random_voice(voice_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "afd37773",
   "metadata": {},
   "source": [
    "#### Generate with saved speaker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9b27ff26",
   "metadata": {},
   "outputs": [],
   "source": [
    "sample_rate = 48000\n",
    "speaker = 'random'\n",
    "voice_path = 'test_voice.pt'\n",
    "\n",
    "example_text = 'В недрах тундры выдры в г+етрах т+ырят в вёдра ядра к+едров.'\n",
    "\n",
    "audio = model.apply_tts(text=example_text,\n",
    "                        speaker=speaker,\n",
    "                        sample_rate=sample_rate,\n",
    "                        voice_path=voice_path)\n",
    "print(example_text)\n",
    "display(Audio(audio, rate=sample_rate))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3987bc23",
   "metadata": {
    "heading_collapsed": true,
    "id": "3987bc23"
   },
   "source": [
    "## V2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d8214b43",
   "metadata": {
    "hidden": true,
    "id": "d8214b43"
   },
   "source": [
    "### One speaker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c8f886e8",
   "metadata": {
    "hidden": true,
    "id": "c8f886e8"
   },
   "outputs": [],
   "source": [
    "import torch\n",
    "\n",
    "language = 'ru'\n",
    "speaker = 'kseniya_v2'\n",
    "sample_rate = 16000\n",
    "device = torch.device('cpu')\n",
    "model, example_text = torch.hub.load(repo_or_dir='snakers4/silero-models',\n",
    "                                     model='silero_tts',\n",
    "                                     language=language,\n",
    "                                     speaker=speaker)\n",
    "model.to(device)  # gpu or cpu"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ebe40114",
   "metadata": {
    "hidden": true,
    "id": "ebe40114"
   },
   "outputs": [],
   "source": [
    "audio = model.apply_tts(texts=[example_text],\n",
    "                        sample_rate=sample_rate)\n",
    "\n",
    "print(example_text)\n",
    "display(Audio(audio[0], rate=sample_rate))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fae7bbef",
   "metadata": {
    "hidden": true,
    "id": "fae7bbef"
   },
   "source": [
    "### Multi speaker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7bdb5e65",
   "metadata": {
    "hidden": true,
    "id": "7bdb5e65"
   },
   "outputs": [],
   "source": [
    "import torch\n",
    "\n",
    "language = 'multi'\n",
    "speaker = 'multi_v2'\n",
    "sample_rate = 16000\n",
    "device = torch.device('cpu')\n",
    "model, avail_speakers = torch.hub.load(repo_or_dir='snakers4/silero-models',\n",
    "                                       model='silero_tts',\n",
    "                                       language=language,\n",
    "                                       speaker=speaker)\n",
    "model.to(device)  # gpu or cpu"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75f00424",
   "metadata": {
    "hidden": true,
    "id": "75f00424"
   },
   "outputs": [],
   "source": [
    "speaker = 'dilyara'\n",
    "example_text = avail_speakers['baya']['example']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "968a6411",
   "metadata": {
    "hidden": true,
    "id": "968a6411"
   },
   "outputs": [],
   "source": [
    "audio = model.apply_tts(texts=[example_text],\n",
    "                        speakers=[speaker],\n",
    "                        sample_rate=sample_rate)\n",
    "\n",
    "print(example_text)\n",
    "display(Audio(audio[0], rate=sample_rate))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1da56a27",
   "metadata": {
    "heading_collapsed": true,
    "id": "1da56a27"
   },
   "source": [
    "## V1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "833cK1e1Gzmp",
   "metadata": {
    "hidden": true,
    "id": "833cK1e1Gzmp"
   },
   "source": [
    "These examples are for older models and obsolete"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "stupid-naples",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-03-29T06:46:39.993648Z",
     "start_time": "2021-03-29T06:46:39.052349Z"
    },
    "hidden": true,
    "id": "stupid-naples"
   },
   "outputs": [],
   "source": [
    "import torch\n",
    "\n",
    "language = 'ru'\n",
    "speaker = 'kseniya_16khz'\n",
    "device = torch.device('cpu')\n",
    "model, symbols, sample_rate, example_text, apply_tts = torch.hub.load(repo_or_dir='snakers4/silero-models',\n",
    "                                                                      model='silero_tts',\n",
    "                                                                      language=language,\n",
    "                                                                      speaker=speaker)\n",
    "model = model.to(device)  # gpu or cpu"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "indirect-berry",
   "metadata": {
    "hidden": true,
    "id": "indirect-berry"
   },
   "outputs": [],
   "source": [
    "audio = apply_tts(texts=[example_text],\n",
    "                  model=model,\n",
    "                  sample_rate=sample_rate,\n",
    "                  symbols=symbols,\n",
    "                  device=device)\n",
    "\n",
    "print(example_text)\n",
    "display(Audio(audio[0], rate=sample_rate))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "n-IHQN_5KA_A",
   "metadata": {
    "hidden": true,
    "id": "n-IHQN_5KA_A"
   },
   "source": [
    "### Enhance synthesis with logmmse"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ivNvVXhLKbmA",
   "metadata": {
    "hidden": true,
    "id": "ivNvVXhLKbmA"
   },
   "outputs": [],
   "source": [
    "!pip install -q logmmse"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "pLMPBH_CMAzh",
   "metadata": {
    "hidden": true,
    "id": "pLMPBH_CMAzh"
   },
   "source": [
    "You can try to enhance synthesized audio with logmmse algorithm, though it could demand parameters tuning for the particular speaker."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6b048VLuzgDF",
   "metadata": {
    "hidden": true,
    "id": "6b048VLuzgDF"
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from logmmse import logmmse\n",
    "\n",
    "enhanced = logmmse(np.array(audio[0]), sample_rate, output_file=None, initial_noise=1, window_size=160, noise_threshold=0.15)\n",
    "display(Audio(enhanced, rate=sample_rate))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "Pwg_AYTCmufA",
   "metadata": {
    "id": "Pwg_AYTCmufA"
   },
   "source": [
    "# Minimal Example to Run Locally "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "Phw8EAVBJGW8",
   "metadata": {
    "id": "Phw8EAVBJGW8"
   },
   "source": [
    "## Dependencies and Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "pLTZK0O7JPHT",
   "metadata": {
    "cellView": "form",
    "id": "pLTZK0O7JPHT"
   },
   "outputs": [],
   "source": [
    "#@title Install dependencies\n",
    "\n",
    "!pip install -q torch==1.10"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b9e704a",
   "metadata": {},
   "source": [
    "## V4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b8281068",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import torch\n",
    "\n",
    "device = torch.device('cpu')\n",
    "torch.set_num_threads(4)\n",
    "local_file = 'model.pt'\n",
    "\n",
    "if not os.path.isfile(local_file):\n",
    "    torch.hub.download_url_to_file('https://models.silero.ai/models/tts/ru/v4_ru.pt',\n",
    "                                   local_file)  \n",
    "\n",
    "model = torch.package.PackageImporter(local_file).load_pickle(\"tts_models\", \"model\")\n",
    "model.to(device)\n",
    "\n",
    "example_text = 'В недрах тундры выдры в г+етрах т+ырят в вёдра ядра кедров.'\n",
    "sample_rate = 48000\n",
    "speaker='baya'\n",
    "\n",
    "audio_paths = model.save_wav(text=example_text,\n",
    "                             speaker=speaker,\n",
    "                             sample_rate=sample_rate)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "04286bd0",
   "metadata": {
    "id": "04286bd0"
   },
   "source": [
    "## V2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31a041ac",
   "metadata": {
    "id": "31a041ac"
   },
   "source": [
    "### One speaker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "337e757f",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-06-18T07:07:51.425251Z",
     "start_time": "2021-06-18T07:07:49.489260Z"
    },
    "id": "337e757f"
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import torch\n",
    "\n",
    "device = torch.device('cpu')\n",
    "torch.set_num_threads(4)\n",
    "local_file = 'model.pt'\n",
    "\n",
    "if not os.path.isfile(local_file):\n",
    "    torch.hub.download_url_to_file('https://models.silero.ai/models/tts/ru/v2_kseniya.pt',\n",
    "                                   local_file)  \n",
    "\n",
    "model = torch.package.PackageImporter(local_file).load_pickle(\"tts_models\", \"model\")\n",
    "model.to(device)\n",
    "\n",
    "example_batch = ['В недрах тундры выдры в г+етрах т+ырят в вёдра ядра кедров.',\n",
    "                 'Котики - это жидкость!',\n",
    "                 'М+ама М+илу м+ыла с м+ылом.']\n",
    "sample_rate = 16000\n",
    "\n",
    "audio_paths = model.save_wav(texts=example_batch,\n",
    "                             sample_rate=sample_rate)\n",
    "print(audio_paths)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3998406",
   "metadata": {
    "id": "e3998406"
   },
   "source": [
    "### Multi speaker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "678f0a98",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-06-18T07:16:46.917813Z",
     "start_time": "2021-06-18T07:16:28.628593Z"
    },
    "id": "678f0a98"
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import torch\n",
    "\n",
    "device = torch.device('cpu')\n",
    "torch.set_num_threads(4)\n",
    "local_file = 'model_multi.pt'\n",
    "speakers = ['aidar', 'baya', 'kseniya', 'irina', 'ruslan', 'natasha',\n",
    "                    'thorsten', 'tux', 'gilles', 'lj', 'dilyara']\n",
    "\n",
    "if not os.path.isfile(local_file):\n",
    "    torch.hub.download_url_to_file('https://models.silero.ai/models/tts/multi/v2_multi.pt',\n",
    "                                   local_file)  \n",
    "\n",
    "model = torch.package.PackageImporter(local_file).load_pickle(\"tts_models\", \"model\")\n",
    "model.to(device)\n",
    "\n",
    "example_batch = ['В н+едрах т+ундры в+ыдры в г+етрах т+ырят в в+ёдра +ядра к+едров.',\n",
    "                 'Fischers Fritze fischt frische Fische',\n",
    "                 'Can you can a canned can into an un-canned can?']\n",
    "example_speakers = ['baya', 'baya', 'baya']\n",
    "sample_rate = 16000\n",
    "\n",
    "audio_paths = model.save_wav(texts=example_batch,\n",
    "                             speakers=example_speakers,\n",
    "                             sample_rate=sample_rate)\n",
    "print(audio_paths)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92990cca",
   "metadata": {
    "id": "92990cca"
   },
   "source": [
    "## V1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "g2t4hX0Im1U_",
   "metadata": {
    "id": "g2t4hX0Im1U_"
   },
   "source": [
    "We have received a lot of questions regarding the packaging requirements and utils from the `silero-models` repo from people trying to run models locally standalone (on their desktop for example). The project is packaged using `torch.hub` utils which basically are in the `hubconf.py` [file](https://github.com/snakers4/silero-models/blob/master/hubconf.py) and `tts_utils.py` [file](https://github.com/snakers4/silero-models/blob/master/src/silero/tts_utils.py).\n",
    "\n",
    "For some reason this is very difficult to understand for some users. Also the `hubconf.py` contains some dependecies, which may not be necessarily required when running TTS for example on your desktop, i.e. `torchaudio` and `omegaconf`.\n",
    "\n",
    "The following example is a minimal standalone example for such a use-case. It has very little external dependecies (essentially just `torch`, the rest is just standard python library). It basically does the following:\n",
    "\n",
    "- Loads one of the 16 kHz models (I just chose one randomly), listed on the models.yml [file](https://github.com/snakers4/silero-models/blob/master/models.yml) locally and uses it as cache;\n",
    "- The `symbols` are taken from the same  models.yml file;\n",
    "- `apply_tts` is just one of the utils we provide in the project;\n",
    "- The rest is self-explanatory;\n",
    "\n",
    "In order to use this example, you will need to handle the resulting audios by yourself."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "_-S9KQ19mzpy",
   "metadata": {
    "id": "_-S9KQ19mzpy"
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import wave\n",
    "import torch\n",
    "import contextlib\n",
    "\n",
    "\n",
    "torch.set_grad_enabled(False)\n",
    "device = torch.device('cpu')\n",
    "torch.set_num_threads(4)  # safe optimal value, i.e. 2 CPU cores, does not work properly in colab\n",
    "symbols = '_~абвгдеёжзийклмнопрстуфхцчшщъыьэюя +.,!?…:;–'\n",
    "local_file = 'model.jit'\n",
    "\n",
    "\n",
    "if not os.path.isfile(local_file):\n",
    "  torch.hub.download_url_to_file('https://models.silero.ai/models/tts/ru/v1_kseniya_16000.jit',\n",
    "                                 local_file)\n",
    "\n",
    "if not os.path.isfile('tts_utils.py'):\n",
    "  torch.hub.download_url_to_file('https://raw.githubusercontent.com/snakers4/silero-models/master/src/silero/tts_utils.py',\n",
    "                                 'tts_utils.py')\n",
    "  from tts_utils import apply_tts  # modify these utils and use them your project\n",
    "  \n",
    "\n",
    "model = torch.jit.load('model.jit',\n",
    "                       map_location=device)\n",
    "model.eval()\n",
    "example_batch = ['В н+едрах т+ундры в+ыдры в г+етрах т+ырят в в+ёдра +ядра к+едров.',\n",
    "                 'К+отики - +это ж+идкость!',\n",
    "                 'М+ама М+илу м+ыла с м+ылом.']\n",
    "sample_rate = 16000\n",
    "model = model.to(device)\n",
    "\n",
    "audio = apply_tts(texts=example_batch,\n",
    "                  model=model,\n",
    "                  sample_rate=sample_rate,\n",
    "                  symbols=symbols,\n",
    "                  device=device)\n",
    "\n",
    "def write_wave(path, audio, sample_rate):\n",
    "    \"\"\"Writes a .wav file.\n",
    "    Takes path, PCM audio data, and sample rate.\n",
    "    \"\"\"\n",
    "    with contextlib.closing(wave.open(path, 'wb')) as wf:\n",
    "        wf.setnchannels(1)\n",
    "        wf.setsampwidth(2)\n",
    "        wf.setframerate(sample_rate)\n",
    "        wf.writeframes(audio)\n",
    "\n",
    "for i, _audio in enumerate(audio):\n",
    "  write_wave(path=f'test_{str(i).zfill(3)}.wav',\n",
    "             audio=(audio[i] * 32767).numpy().astype('int16'),\n",
    "             sample_rate=16000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "_pcIug4No2Mn",
   "metadata": {
    "id": "_pcIug4No2Mn"
   },
   "outputs": [],
   "source": [
    "from IPython.display import Audio, display\n",
    "display(Audio('test_000.wav', rate=16000))\n",
    "display(Audio('test_001.wav', rate=16000))\n",
    "display(Audio('test_002.wav', rate=16000))"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "examples_tts.ipynb",
   "provenance": [],
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.11"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}